<?php
declare(strict_types=1);

namespace app\common;

/**
 * 文件上传配置类
 * 统一管理系统中所有文件上传和下载相关的配置
 */
class FileUploadConfig
{
    /**
     * 文件存储基础路径（相对于public目录）
     */
    const BASE_PATH = 'uploads';
    
    /**
     * 文件存储路径配置（统一按年月格式存储）
     * 格式：模块名 => 路径模板
     */
    const MODULE_PATHS = [
        // 所有模块统一使用相同的存储路径格式：uploads/年月
        'default' => 'uploads/{date}',
        
        // 知识笔记附件存储路径（统一格式）
        'article' => 'uploads/{date}',
        
        // 磁盘文件存储路径（统一格式）
        'disk' => 'uploads/{date}',
        
        // 用户头像存储路径（统一格式）
        'avatar' => 'uploads/{date}',
        
        // 临时文件存储路径（统一格式）
        'temp' => 'uploads/{date}',
        
        // 导入导出文件存储路径（统一格式）
        'import_export' => 'uploads/{date}',
    ];
    
    /**
     * 允许的文件类型配置
     */
    const ALLOWED_EXTENSIONS = [
        'image' => 'jpg,jpeg,png,gif,bmp,webp',
        'document' => 'doc,docx,xls,xlsx,ppt,pptx,pdf,txt',
        'archive' => 'zip,rar,7z,tar,gz',
        'video' => 'mp4,avi,wmv,mov,flv,m4v,3gp',
        'audio' => 'mp3,wav,wma,flac,midi',
        'all' => 'jpg,jpeg,png,gif,bmp,webp,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,7z,tar,gz,mp4,avi,wmv,mov,flv,m4v,3gp,mp3,wav,wma,flac,midi'
    ];
    
    /**
     * 默认文件大小限制（单位：MB）
     */
    const DEFAULT_MAX_SIZE = 50;
    
    /**
     * 各类型文件大小限制（单位：MB）
     */
    const MAX_SIZES = [
        'image' => 10,
        'document' => 50,
        'archive' => 100,
        'video' => 200,
        'audio' => 50,
    ];
    
    /**
     * 获取模块文件存储路径
     * @param string $module 模块名
     * @param string|null $date 日期（格式：Ym，为空则使用当前日期）
     * @return string 文件存储路径
     */
    public static function getModulePath(string $module, ?string $date = null): string
    {
        $date = $date ?: date('Ym');
        $pathTemplate = self::MODULE_PATHS[$module] ?? self::MODULE_PATHS['default'];
        
        return str_replace('{date}', $date, $pathTemplate);
    }
    
    /**
     * 获取完整的文件存储路径（包含public目录）
     * @param string $module 模块名
     * @param string|null $date 日期
     * @return string 完整的文件存储路径
     */
    public static function getFullPath(string $module, ?string $date = null): string
    {
        $modulePath = self::getModulePath($module, $date);
        return app()->getRootPath() . 'public' . DIRECTORY_SEPARATOR . $modulePath;
    }
    
    /**
     * 获取文件访问URL路径
     * @param string $module 模块名
     * @param string $filename 文件名
     * @param string|null $date 日期
     * @return string 文件访问URL路径
     */
    public static function getFileUrl(string $module, string $filename, ?string $date = null): string
    {
        $modulePath = self::getModulePath($module, $date);
        return $modulePath . '/' . $filename;
    }
    
    /**
     * 获取文件物理路径
     * @param string $module 模块名
     * @param string $filename 文件名
     * @param string|null $date 日期
     * @return string 文件物理路径
     */
    public static function getFilePath(string $module, string $filename, ?string $date = null): string
    {
        $fullPath = self::getFullPath($module, $date);
        return $fullPath . DIRECTORY_SEPARATOR . $filename;
    }
    
    /**
     * 获取允许的文件扩展名
     * @param string $type 文件类型
     * @return string 允许的扩展名字符串
     */
    public static function getAllowedExtensions(string $type = 'all'): string
    {
        return self::ALLOWED_EXTENSIONS[$type] ?? self::ALLOWED_EXTENSIONS['all'];
    }
    
    /**
     * 获取文件大小限制
     * @param string $type 文件类型
     * @return int 文件大小限制（字节）
     */
    public static function getMaxSize(string $type = 'default'): int
    {
        $sizeMB = self::MAX_SIZES[$type] ?? self::DEFAULT_MAX_SIZE;
        return $sizeMB * 1024 * 1024; // 转换为字节
    }
    
    /**
     * 确保目录存在
     * @param string $module 模块名
     * @param string|null $date 日期
     * @return string 创建的目录路径
     */
    public static function ensureDirectoryExists(string $module, ?string $date = null): string
    {
        $fullPath = self::getFullPath($module, $date);
        
        if (!is_dir($fullPath)) {
            mkdir($fullPath, 0755, true);
        }
        
        return $fullPath;
    }
    
    /**
     * 标准化文件路径，统一使用正斜杠
     * @param string $path 文件路径
     * @return string 标准化后的路径
     */
    public static function normalizePath(string $path): string
    {
        return str_replace('\\', '/', $path);
    }
    
    /**
     * 生成安全的文件名
     * @param string $originalName 原始文件名
     * @param bool $keepExtension 是否保留扩展名
     * @return string 安全的文件名
     */
    public static function generateSafeFileName(string $originalName, bool $keepExtension = true): string
    {
        $nameWithoutExt = pathinfo($originalName, PATHINFO_FILENAME);
        $ext = $keepExtension ? '.' . pathinfo($originalName, PATHINFO_EXTENSION) : '';
        
        // 生成安全的文件名：只保留大小写字母和数字
        $safeName = preg_replace('/[^a-zA-Z0-9]/', '', $nameWithoutExt);
        
        // 限制长度
        if (strlen($safeName) > 50) {
            $safeName = substr($safeName, 0, 50);
        }
        
        // 确保不为空
        if (empty($safeName)) {
            $safeName = 'file' . rand(1000, 9999);
        }
        
        // 生成唯一文件名：使用安全的文件名加上随机数字确保唯一性
        return $safeName . rand(1000, 9999) . $ext;
    }
    
    /**
     * 获取文件下载路径
     * 兼容新旧文件路径，优先尝试新路径，不存在则尝试旧路径
     * @param array $file 文件信息数组
     * @return string|null 文件物理路径，不存在则返回null
     */
    public static function getDownloadPath(array $file): ?string
    {
        if (empty($file['filepath'])) {
            return null;
        }
        
        // 首先尝试直接路径（新上传的文件）
        // 兼容性处理：确保filepath以/开头
        $filepath = $file['filepath'];
        if (substr($filepath, 0, 1) !== '/') {
            $filepath = '/' . $filepath;
        }
        $filePath = app()->getRootPath() . 'public' . $filepath;
        $filePath = self::normalizePath($filePath);
        
        // 如果文件不存在，尝试旧路径（包含模块名的路径）
        if (!file_exists($filePath)) {
            // 尝试根据模块名构建旧路径
            if (!empty($file['module'])) {
                // 从filepath中提取文件名
                $filename = basename($file['filepath']);
                
                // 尝试旧路径格式：uploads/{module}/{date}/{filename}
                if (preg_match('/uploads\/(\d{6})\/(.+)/', $file['filepath'], $matches)) {
                    $date = $matches[1];
                    $oldPath = 'uploads/' . $file['module'] . '/' . $date . '/' . $filename;
                    $filePath = app()->getRootPath() . 'public/' . $oldPath;
                    $filePath = self::normalizePath($filePath);
                }
                
                // 如果仍然不存在，尝试storage路径
                if (!file_exists($filePath)) {
                    // 兼容性处理：确保filepath以/开头
                    $storagePath = $file['filepath'];
                    if (substr($storagePath, 0, 1) !== '/') {
                        $storagePath = '/' . $storagePath;
                    }
                    $filePath = app()->getRootPath() . 'public/storage' . $storagePath;
                    $filePath = self::normalizePath($filePath);
                }
            }
        }
        
        // 标准化文件路径，确保Windows系统下路径分隔符正确
        $filePath = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $filePath);
        
        return file_exists($filePath) ? $filePath : null;
    }
    
    /**
     * 检查文件扩展名是否允许
     * @param string $extension 文件扩展名
     * @param string $type 文件类型
     * @return bool 是否允许
     */
    public static function isAllowedExtension(string $extension, string $type = 'all'): bool
    {
        $allowedExtensions = self::getAllowedExtensions($type);
        $extensionArray = explode(',', $allowedExtensions);
        return in_array(strtolower($extension), array_map('strtolower', $extensionArray));
    }
    
    /**
     * 获取文件存储路径（相对于public目录）
     * @param string $module 模块名
     * @param string $action 操作类型
     * @param string|null $date 日期
     * @return string 文件存储路径
     */
    public static function getStoragePath(string $module, string $action = '', ?string $date = null): string
    {
        // 如果指定了操作类型，尝试使用模块+操作的组合路径
        if (!empty($action)) {
            $moduleKey = $module . '_' . $action;
            if (isset(self::MODULE_PATHS[$moduleKey])) {
                $pathTemplate = self::MODULE_PATHS[$moduleKey];
            } else {
                $pathTemplate = self::MODULE_PATHS[$module] ?? self::MODULE_PATHS['default'];
            }
        } else {
            $pathTemplate = self::MODULE_PATHS[$module] ?? self::MODULE_PATHS['default'];
        }
        
        $date = $date ?: date('Ym');
        $path = str_replace('{date}', $date, $pathTemplate);
        
        // 确保返回的路径使用正斜杠
        return self::normalizePath($path);
    }
    

}